/*
 * Zirco Browser for Android
 * 
 * Copyright (C) 2010 - 2012 J. Devauchelle and contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 3 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

package org.zirco.ui.components;

import org.zirco.controllers.Controller;
import org.zirco.ui.activities.MainActivity;
import org.zirco.utils.ApplicationUtils;
import org.zirco.utils.Constants;
import org.zirco.utils.UrlUtils;

import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.net.http.SslCertificate.DName;
import android.net.http.SslError;
import android.webkit.HttpAuthHandler;
import android.webkit.SslErrorHandler;
import android.webkit.WebView;
import android.webkit.WebView.HitTestResult;
import android.webkit.WebViewClient;
import de.idgard.R;
import de.idgard.android.addon.annotation.ContainerFix;
import de.idgard.android.addon.annotation.Intervention;
import de.idgard.android.addon.services.GlobalServiceRegistry;
import de.idgard.android.addon.ui.AddonUIManager;

/**
 * Convenient extension of WebViewClient.
 */
public class CustomWebViewClient extends WebViewClient {

	private MainActivity mMainActivity;

	public CustomWebViewClient(MainActivity mainActivity) {
		super();
		mMainActivity = mainActivity;
	}

	@Intervention
	private boolean checkIfUnisconCertificate(DName dname) {
		return AddonUIManager.getInstance().checkIfCerificateIssuerIsUniscon(dname);
	}

	@Intervention
	private void addonPageFinishedHandling(String url) {
		AddonUIManager.getInstance().checkLoadedUrlForCookiesAndAdjustStateAndSettings(url);
	}

	@Intervention
	private void addonPageStartedHandling(String url) {
		AddonUIManager.getInstance().checkUrlAndUpdateStateAndUI(url);
	}

	@Override
	public void onPageFinished(WebView view, String url) {
		((CustomWebView) view).notifyPageFinished();
		mMainActivity.onPageFinished(url);
		addonPageFinishedHandling(url);
		super.onPageFinished(view, url);
	}

	@Override
	public void onPageStarted(WebView view, String url, Bitmap favicon) {

		// Some magic here: when performing WebView.loadDataWithBaseURL, the url
		// is "file:///android_asset/startpage,
		// whereas when the doing a "previous" or "next", the url is
		// "about:start", and we need to perform the
		// loadDataWithBaseURL here, otherwise it won't load.
		if (url.equals(Constants.URL_ABOUT_START)) {
			ApplicationUtils.loadStartPage(view, view.getContext());
		} else {
			addonPageStartedHandling(url);
		}

		((CustomWebView) view).notifyPageStarted();
		mMainActivity.onPageStarted(url);

		super.onPageStarted(view, url, favicon);
	}

	@Override
	public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {

		if (checkIfUnisconCertificate(error.getCertificate().getIssuedBy())) {
			handler.proceed();
			return;
		}
		StringBuilder sb = new StringBuilder();

		sb.append(view.getResources().getString(R.string.Commons_SslWarningsHeader));
		sb.append("\n\n");

		if (error.hasError(SslError.SSL_UNTRUSTED)) {
			sb.append(" - ");
			sb.append(view.getResources().getString(R.string.Commons_SslUntrusted));
			sb.append("\n");
		}

		if (error.hasError(SslError.SSL_IDMISMATCH)) {
			sb.append(" - ");
			sb.append(view.getResources().getString(R.string.Commons_SslIDMismatch));
			sb.append("\n");
		}

		if (error.hasError(SslError.SSL_EXPIRED)) {
			sb.append(" - ");
			sb.append(view.getResources().getString(R.string.Commons_SslExpired));
			sb.append("\n");
		}

		if (error.hasError(SslError.SSL_NOTYETVALID)) {
			sb.append(" - ");
			sb.append(view.getResources().getString(R.string.Commons_SslNotYetValid));
			sb.append("\n");
		}

		ApplicationUtils.showContinueCancelDialog(view.getContext(), android.R.drawable.ic_dialog_info, view.getResources().getString(R.string.Commons_SslWarning),
				sb.toString(), new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						handler.proceed();
					}

				}, new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						dialog.dismiss();
						handler.cancel();
					}
				});
	}

	@Override
	@ContainerFix
	public boolean shouldOverrideUrlLoading(WebView view, String url) {
		
		if (isExternalApplicationUrl(url)) {
			mMainActivity.onExternalApplicationUrl(url);
			return true;

		} else if (url.startsWith(Constants.URL_ACTION_SEARCH)) {
			String searchTerm = url.replace(Constants.URL_ACTION_SEARCH, "");

			String searchUrl = Controller.getInstance().getPreferences().getString(Constants.PREFERENCES_GENERAL_SEARCH_URL, Constants.URL_SEARCH_GOOGLE);
			String newUrl = String.format(searchUrl, searchTerm);

			view.loadUrl(newUrl);
			return true;

		} else if (view.getHitTestResult() != null && view.getHitTestResult().getType() == HitTestResult.EMAIL_TYPE) {
			mMainActivity.onMailTo(url);
			return true;

		} else {

			// If the url is not from GWT mobile view, and is in the mobile view
			// url list, then load it with GWT.
			if ((!url.startsWith(Constants.URL_GOOGLE_MOBILE_VIEW_NO_FORMAT)) && (UrlUtils.checkInMobileViewUrlList(view.getContext(), url))) {

				String newUrl = String.format(Constants.URL_GOOGLE_MOBILE_VIEW, url);
				view.loadUrl(newUrl);
				return true;

			} else {
				((CustomWebView) view).resetLoadedUrl();
				mMainActivity.onUrlLoading(url);
				return false;
			}
		}
	}

	@Override
	@Intervention
	public void onReceivedHttpAuthRequest(WebView view, final HttpAuthHandler handler, final String host, final String realm) {
	
		handler.proceed(GlobalServiceRegistry.instance().getBrowserUtilityService().getIDGardData().getIdgardId(), GlobalServiceRegistry.instance()
				.getBrowserUtilityService().getIDGardData().getJsessionId());
		
	}

	private boolean isExternalApplicationUrl(String url) {
		return url.startsWith("vnd.") || url.startsWith("rtsp://") || url.startsWith("itms://") || url.startsWith("itpc://");
	}

}
